home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / small_c.arc / CLIB.ARC < prev    next >
Text File  |  1985-09-15  |  54KB  |  2,144 lines

  1. >>> CLIB.DEF 1619
  2. /*
  3. ** CLIB.DEF -- Definitions for Small-C library functions.
  4. **
  5. ** Copyright 1983  L. E. Payne and J. E. Hendrix
  6. */
  7.  
  8. /*
  9. ** Misc parameters
  10. */
  11. #define MAXFILES 20  /* maximum open files */
  12. #define DOSEOF   26  /* DOS end-of-file byte */
  13. #define ARCHIVE  32  /* file archive bit */
  14.  
  15. /*
  16. ** DOS function calls
  17. */
  18. #define CREATE   60  /* make file */
  19. #define OPEN     61  /* open file */
  20. #define CLOSE    62  /* close file or device */
  21. #define READ     63  /* read from a file */
  22. #define WRITE    64  /* write to a file */
  23. #define DELETE   65  /* delete file */
  24. #define SEEK     66  /* seek within a file */
  25. #define CONTROL  68  /* control device */
  26. #define FORCE    70  /* force use of a handle */
  27. #define RETDOS   76  /* close files and return to DOS */
  28. #define FNDFIL   78  /* find first occurrence of a file */
  29. #define FNDNXT   79  /* find next occurrence of a file */
  30. #define RENAME   86  /* rename file */
  31.  
  32. /*
  33. ** File status bits
  34. */
  35. #define OPNBIT   1  /* open condition */
  36. #define EOFBIT   2  /* end-of-file condition */
  37. #define ERRBIT   4  /* error condition */
  38.  
  39. /*
  40. ** File positioning origins
  41. */
  42. #define FROM_BEG  0  /* from beginning of file */
  43. #define FROM_CUR  1  /* from current position */
  44. #define FROM_END  2  /* from end of file */
  45.  
  46. /*
  47. ** Buffer usage codes
  48. ** NULL means the buffer is not used.
  49. */
  50. #define EMPTY     1  /* buffer is currently empty */
  51. #define IN        2  /* buffer is currently holding input data */
  52. #define OUT       3  /* buffer is currently holding output data */
  53.  
  54. /*
  55. ** ASCII characters
  56. */
  57. #define ABORT    3
  58. #define RUB      8
  59. #define PAUSE   19
  60. #define WIPE    24
  61. #define DEL    127
  62.  
  63. >>> ABS.C 117
  64. /*
  65. ** abs -- returns absolute value of nbr
  66. */
  67. abs(nbr)  int nbr; {
  68.   if(nbr < 0) return (-nbr);
  69.   return (nbr);
  70.   }
  71.  
  72. >>> ATOI.C 309
  73. #define NOCCARGC  /* no argument count passing */
  74. /*
  75. ** atoi(s) - convert s to integer.
  76. */
  77. atoi(s) char *s; {
  78.   int sign, n;
  79.   while(isspace(*s)) ++s;
  80.   sign = 1;
  81.   switch(*s) {
  82.     case '-': sign = -1;
  83.     case '+': ++s;
  84.     }
  85.   n = 0;
  86.   while(isdigit(*s)) n = 10 * n + *s++ - '0';
  87.   return (sign * n);
  88.   }
  89.  
  90. >>> ATOIB.C 485
  91. #define NOCCARGC  /* no argument count passing */
  92. /*
  93. ** atoib(s,b) - Convert s to "unsigned" integer in base b.
  94. **              NOTE: This is a non-standard function.
  95. */
  96. atoib(s, b) char *s; int b; {
  97.   int n, digit;
  98.   n = 0;
  99.   while(isspace(*s)) ++s;
  100.   while((digit = (127 & *s++)) >= '0') {
  101.     if(digit >= 'a')      digit -= 87;
  102.     else if(digit >= 'A') digit -= 55;
  103.     else                  digit -= '0';
  104.     if(digit >= b) break;
  105.     n = b * n + digit;
  106.     }
  107.   return (n);
  108.   }
  109.  
  110.  
  111. >>> AUXBUF.C 838
  112. #define NOCCARGC  /* no argument count passing */
  113. #include "stdio.h"
  114. #include "clib.def"
  115. extern int
  116.   _bufsiz[MAXFILES],  /* size of buffer */
  117.   _bufptr[MAXFILES];  /* aux buffer address */
  118.  
  119. /*
  120. ** auxbuf -- allocate an auxiliary input buffer for fd
  121. **   fd = file descriptor of an open file
  122. ** size = size of buffer to be allocated
  123. ** Returns NULL on success, else ERR.
  124. ** Note: Ungetc() still works.
  125. **       A 2nd call allocates a new buffer replacing old one.
  126. **       If fd is a device, buffer is allocated but ignored.
  127. **       Buffer stays allocated when fd is closed or new one is allocated.
  128. **       May be used on a closed fd.
  129. */
  130. auxbuf(fd, size) int fd; char *size; {   /* fake unsigned */
  131.   if(!size || avail(NO) < size) return (ERR);
  132.   _bufptr[fd] = malloc(size);
  133.   _bufsiz[fd] = size;
  134.   _empty(fd, NO);
  135.   return (NULL);
  136.   }
  137.  
  138. >>> AVAIL.C 399
  139. #define NOCCARGC  /* no argument count passing */
  140. extern char *_memptr;
  141. /*
  142. ** Return the number of bytes of available memory.
  143. ** In case of a stack overflow condition, if 'abort'
  144. ** is non-zero the program aborts with an 'S' clue,
  145. ** otherwise zero is returned.
  146. */
  147. avail(abort) int abort; {
  148.   char x;
  149.   if(&x < _memptr) {
  150.     if(abort) exit('M');
  151.     return (0);
  152.     }
  153.   return (&x - _memptr);
  154.   }
  155.  
  156. >>> BSEEK.C 779
  157. #define NOCCARGC  /* no argument count passing */
  158. #include "stdio.h"
  159. #include "clib.def"
  160. extern int _nextc[], _bufuse[];
  161. /*
  162. ** Position fd to the character in file indicated by "offset."
  163. ** "Offset" is the address of a long integer or array of two
  164. ** integers containing the offset, low word first.
  165. ** 
  166. **     BASE     OFFSET-RELATIVE-TO
  167. **       0      beginning of file
  168. **       1      current byte in file
  169. **       2      end of file (minus offset)
  170. **
  171. ** Returns NULL on success, else EOF.
  172. */
  173. bseek(fd, offset, base) int fd, offset[], base; {
  174.   int hi, lo;
  175.   if(!_mode(fd) || !_bufuse[fd]) return (EOF);
  176.   if(_adjust(fd)) return (EOF);
  177.   lo = offset[0];
  178.   hi = offset[1];
  179.   if(!_seek(base, fd, &hi, &lo)) return (EOF);
  180.   _nextc[fd] = EOF;
  181.   _clreof(fd);
  182.   return (NULL);
  183.   }
  184.  
  185. >>> BTELL.C 494
  186. #define NOCCARGC  /* no arg count passing */
  187. #include "stdio.h"
  188. #include "clib.def"
  189. extern int _bufuse[];
  190. /*
  191. ** Retrieve offset to next character in fd.
  192. ** "Offset" must be the address of a long int or
  193. ** a 2-element int array.  The offset is placed in
  194. ** offset in low, high order.
  195. */
  196. btell(fd, offset) int fd, offset[]; {
  197.   if(!_mode(fd) || !_bufuse[fd]) return (EOF);
  198.   if(_adjust(fd)) return (EOF);
  199.   offset[0] = offset[1] = 0;
  200.   _seek(FROM_CUR, fd, offset+1, offset);
  201.   return (NULL);
  202.   }
  203. >>> CALL.ASM 3335
  204. ;
  205. ; Small-C Run Time Library for MS/PC-DOS
  206. ;
  207.         extrn   __main: near
  208.         extrn   __memptr: word
  209.  
  210. data   segment public
  211.         dw      1
  212. data   ends
  213.  
  214. stack   segment stack
  215.         dw      32 dup(?)
  216. stack   ends
  217.  
  218. code    segment public
  219.         assume  cs:code
  220. start:
  221.         mov     ax,data         ; set data segment for program
  222.         mov     ds,ax
  223.         mov     ax,es:[2]       ; paragraphs of memory on system
  224.         sub     ax,data         ; paragraphs beyond code segment
  225.         cmp     ax,1000h        ; more than 64K?
  226.         jb      start_1         ; no
  227.         mov     ax,1000h        ; only use 64K
  228. start_1:
  229.         mov     cl,4
  230.         shl     ax,cl           ; byte offset to end of data/free/stack
  231.         cli                     ; disable interrupts
  232.         mov     bx,ds
  233.         mov     ss,bx           ; make data and stack segments coincide
  234.         mov     sp,ax           ; top of stack = end of data/free/stack
  235.         push    ax              ; force sp non-zero (if 64K used)
  236.         sti                     ; reenable interrupts
  237.         mov     ax,stack        ; paragraph following data
  238.         sub     ax,data         ; number of data paragraphs
  239.         shl     ax,cl           ; number of data bytes (offset to free/stack)
  240.         mov     bx,ax
  241.         add     bx,256          ; adjust for minimum stack space
  242.         cmp     bx,sp           ; enough memory?
  243.         jb      start_2         ; yes
  244.         mov     ax,4CFFH        ; no, terminate with exit code FF hex
  245.         int     21H
  246. start_2:
  247.         mov     __memptr,ax     ; set memory allocation pointer
  248. ;
  249. ; ------ cannot run debug with this code -------
  250. ;        mov     bx,sp           ; release unused memory
  251. ;        mov     ah,4AH          ; SETBLOCK
  252. ;        int     21H
  253. ; ----------------------------------------------
  254. ;
  255. ; make sure that es -> psp, because __main requires it
  256. ;
  257.         jmp     __main          ; __main never returns
  258.  
  259.         public  _ccargc
  260. _ccargc:
  261.         mov     al,cl
  262.         xor     ah,ah
  263.         ret
  264.  
  265. ;
  266. ; Test if Secondary (BX) <oper> Primary (AX)
  267. ;
  268. compare macro   name, cond
  269.         public  __&name
  270. __&name:
  271.         cmp     ax,bx
  272.         j&cond  true
  273.         xor     ax,ax   ; returns zero
  274.         ret
  275.         endm
  276. ;
  277.         compare ult,a
  278.         compare ugt,b
  279.         compare ule,ae
  280.         compare uge,be
  281.         compare eq,e
  282.         compare ne,ne
  283.         compare lt,g
  284.         compare gt,l
  285.         compare le,ge
  286.         compare ge,le
  287. ;
  288. ; Logical Negate of Primary
  289. ;
  290.         public  __lneg
  291. __lneg:
  292.         or      ax,ax
  293.         jnz     false
  294. true:   mov     ax,1    ; returns one
  295.         ret
  296. false:  xor     ax,ax   ; returns zero
  297.         ret
  298. ;
  299. ;
  300. ; execute "switch" statement
  301. ;
  302. ;  ax  =  switch value
  303. ; (sp) -> switch table
  304. ;         dw addr1, value1
  305. ;         dw addr2, value2
  306. ;         ...
  307. ;         dw 0
  308. ;        [jmp default]
  309. ;         continuation
  310. ;
  311.         public  __switch
  312. __switch:
  313.         pop     bx              ; bx -> switch table
  314.         jmp     short loop1     ; skip the pre-increment
  315. loop:
  316.         add     bx,4
  317. loop1:
  318.         mov     cx,cs:[bx]
  319.         jcxz    default
  320.         cmp     ax,cs:[bx+2]
  321.         jnz     loop
  322.         jmp     cx              ; target code
  323. default:
  324.         add     bx,2
  325.         jmp     bx              ; default or continuation code
  326.  
  327. code ends
  328.         end     start
  329.  
  330. >>> CALLOC.C 363
  331. #define NOCCARGC  /* no argument count passing */
  332. #include "stdio.h"
  333. /*
  334. ** Cleared-memory allocation of n items of size bytes.
  335. ** n     = Number of items to allocate space for.
  336. ** size  = Size of the items in bytes.
  337. ** Returns the address of the allocated block,
  338. ** else NULL for failure.
  339. */
  340. calloc(n, size) char *n, *size; {
  341.   return (_alloc(n*size, YES));
  342.   }
  343.  
  344. >>> CLEARERR.C 199
  345. #define NOCCARGC  /* no arg count passing */
  346. #include "stdio.h"
  347. #include "clib.def"
  348. extern int _status[];
  349. /*
  350. ** Clear error status for fd.
  351. */
  352. clearerr(fd) int fd; {
  353.   if(_mode(fd)) _clrerr(fd);
  354.   }
  355.  
  356. >>> CSEEK.C 1591
  357. #define NOCCARGC  /* no argument count passing */
  358. #include "stdio.h"
  359. #include "clib.def"
  360. extern int _nextc[], _bufuse[];
  361. /*
  362. ** Position fd to the 128-byte record indicated by
  363. ** "offset" relative to the point indicated by "base."
  364. ** 
  365. **     BASE     OFFSET-RELATIVE-TO
  366. **       0      first record
  367. **       1      current record
  368. **       2      end of file (last record + 1)
  369. **              (offset should be minus)
  370. **
  371. ** Returns NULL on success, else EOF.
  372. */
  373. cseek(fd, offset, base) int fd, offset, base; {
  374.   int newrec, oldrec, hi, lo;
  375.   if(!_mode(fd) || !_bufuse[fd]) return (EOF);
  376.   if(_adjust(fd)) return (EOF);
  377.   switch (base) {
  378.      case 0: newrec = offset;
  379.              break;
  380.      case 1: oldrec = ctell(fd);
  381.              goto calc;
  382.      case 2: hi = lo = 0;
  383.              if(!_seek(FROM_END, fd, &hi, &lo)) return (EOF);
  384.              oldrec = ((lo >> 7) & 511) | (hi << 9);
  385.      calc:
  386.              newrec = oldrec + offset;
  387.              break;
  388.     default: return (EOF);
  389.     }
  390.   lo = (newrec << 7);       /* convert newrec to long int */
  391.   hi = (newrec >> 9) & 127;
  392.   if(!_seek(FROM_BEG, fd, &hi, &lo)) return (EOF);
  393.   _nextc[fd] = EOF;
  394.   _clreof(fd);
  395.   return (NULL);
  396.   }
  397.  
  398. /*
  399. ** Position fd to the character indicated by
  400. ** "offset" within current 128-byte record.
  401. ** Must be on record boundary.
  402. **
  403. ** Returns NULL on success, else EOF.
  404. */
  405. cseekc(fd, offset) int fd, offset; {
  406.   int hi, lo;
  407.   if(!_mode(fd) || isatty(fd) ||
  408.      ctellc(fd) || offset < 0 || offset > 127) return (EOF);
  409.   hi = 0; lo = offset;
  410.   if(!_seek(FROM_CUR, fd, &hi, &lo)) return (EOF);
  411.   return (NULL);
  412.   }
  413.  
  414. >>> CSYSLIB.C 9633
  415. /*
  416. ** CSYSLIB -- System-Level Library Functions
  417. */
  418.  
  419. #define NOCCARGC    /* no argument count passing */
  420. #include "stdio.h"
  421. #include "clib.def"
  422.  
  423. /*
  424. ****************** System Variables ********************
  425. */
  426.  
  427. int
  428.   _cnt=1,            /* arg count for main */
  429.   _vec[20],          /* arg vectors for main */
  430.   _status[MAXFILES] = {OPNBIT, OPNBIT, OPNBIT, OPNBIT, OPNBIT},
  431.   _nextc [MAXFILES] = {EOF, EOF, EOF, EOF, EOF},
  432.   _bufuse[MAXFILES],  /* current buffer usage: NULL, EMPTY, IN, OUT */
  433.   _bufsiz[MAXFILES],  /* size of buffer */
  434.   _bufptr[MAXFILES],  /* aux buffer address */
  435.   _bufnxt[MAXFILES],  /* address of next byte in buffer */
  436.   _bufend[MAXFILES],  /* address of end-of-data in buffer */
  437.   _bufeof[MAXFILES];  /* true if current buffer ends file */
  438.  
  439. char
  440.  *_memptr,           /* pointer to free memory. */
  441.   _arg1[]="*";       /* first arg for main */
  442.  
  443. /*
  444. *************** System-Level Functions *****************
  445. */
  446.  
  447. /*
  448. **  Process command line, allocate default buffer to each fd,
  449. **  execute main(), and exit to DOS.  Must be executed with es=psp.
  450. **  Small default buffers are allocated because a high price is paid for
  451. **  byte-by-byte calls to DOS.  Tests gave these results for a simple
  452. **  copy program:
  453. **
  454. **          chunk size       copy time in seconds
  455. **              1                    36
  456. **              5                    12
  457. **             25                     6
  458. **             50                     6
  459. */
  460. _main() {
  461.   int fd;
  462.   _parse();
  463.   for(fd = 0; fd < MAXFILES; ++fd) auxbuf(fd, 32);
  464.   if(!isatty(stdin))  _bufuse[stdin]  = EMPTY;
  465.   if(!isatty(stdout)) _bufuse[stdout] = EMPTY;
  466.   main(_cnt, _vec);
  467.   exit(0);
  468.   }
  469.  
  470. /*
  471. ** Parse command line and setup argc and argv.
  472. ** Must be executed with es == psp
  473. */
  474. _parse() {
  475.   char *ptr;
  476. #asm
  477.   mov     cl,es:[80h]  ; get parameter string length
  478.   mov     ch,0       
  479.   push    cx           ; save it
  480.   inc     cx
  481.   push    cx           ; 1st __alloc() arg
  482.   mov     ax,1
  483.   push    ax           ; 2nd __alloc() arg
  484.   call    __alloc      ; allocate zeroed memory for args
  485.   add     sp,4
  486.   mov     [bp-2],ax    ; ptr = addr of allocated memory
  487.   pop     cx
  488.   push    es           ; exchange
  489.   push    ds           ; es         (source)
  490.   pop     es           ;    and
  491.   pop     ds           ;        ds  (destination)
  492.   mov     si,81h       ; source offset
  493.   mov     di,[bp-2]    ; destination offset
  494.   rep     movsb        ; move string
  495.   mov     al,0
  496.   stosb                ; terminate with null byte
  497.   push    es
  498.   pop     ds           ; restore ds
  499. #endasm
  500.   _vec[0]=_arg1;       /* first arg = "*" */
  501.   while (*ptr) {
  502.     if(isspace(*ptr)) {++ptr; continue;}
  503.     if(_cnt < 20) _vec[_cnt++] = ptr;
  504.     while(*ptr) {
  505.       if(isspace(*ptr)) {*ptr = NULL; ++ptr; break;}
  506.       ++ptr;
  507.       }
  508.     }
  509.   }
  510.  
  511. /*
  512. ** Open file on specified fd.
  513. */
  514. _open(fn, mode, fd) char *fn, *mode; int *fd; {
  515.   int rw, tfd;
  516.   switch(mode[0]) {
  517.     case 'r': {
  518.       if(mode[1] == '+') rw = 2; else rw = 0;
  519.       if ((tfd = _bdos2((OPEN<<8)|rw, NULL, NULL, fn)) < 0) return (NO);
  520.       break;
  521.       }
  522.     case 'w': {
  523.       if(mode[1] == '+') rw = 2; else rw = 1;
  524.     create:
  525.       if((tfd = _bdos2((CREATE<<8), NULL, ARCHIVE, fn)) < 0) return (NO);
  526.       _bdos2(CLOSE<<8, tfd, NULL, NULL);
  527.       if((tfd = _bdos2((OPEN<<8)|rw, NULL, NULL, fn)) < 0) return (NO);
  528.       break;
  529.       }
  530.     case 'a': {
  531.       if(mode[1] == '+') rw = 2; else rw = 1;
  532.       if((tfd = _bdos2((OPEN<<8)|rw, NULL, NULL, fn)) < 0) goto create;
  533.       if(_bdos2((SEEK<<8)|FROM_END, tfd, NULL, 0) < 0) return (NO);
  534.       break;
  535.       }
  536.     default: return (NO);
  537.     }
  538.   _empty(tfd, YES);
  539.   if(isatty(tfd)) _bufuse[tfd] = NULL;
  540.   *fd = tfd;
  541.   _nextc[tfd]  = EOF;
  542.   _status[tfd] = OPNBIT;
  543.   return (YES);
  544.   }
  545.  
  546. /*
  547. ** Binary-stream input of one byte from fd.
  548. */
  549. _read(fd) int fd; {
  550.   int ch;
  551.   if(_nextc[fd] != EOF) {
  552.     ch = _nextc[fd];
  553.     _nextc[fd] = EOF;
  554.     return (ch&255);
  555.     }
  556.   if(_bufuse[fd]) return(_readbuf(fd));
  557.   switch(_bdos2(READ<<8, fd, 1, &ch)) {
  558.      case 1: return (ch&255);
  559.      case 0: _seteof(fd); return (EOF);
  560.     default: _seterr(fd); return (EOF);
  561.     }
  562.   }
  563.  
  564. /*
  565. ** Fill buffer if necessary, and return next byte.
  566. */
  567. _readbuf(fd) int fd; {
  568.   int got, chunk;
  569.   char *ptr, *max;
  570.   if(_bufuse[fd] == OUT && _flush(fd)) return (EOF);
  571.   while(YES) {
  572.     ptr = _bufnxt[fd];
  573.     if(ptr < _bufend[fd]) {++_bufnxt[fd]; return (*ptr);}
  574.     if(_bufeof[fd]) {_seteof(fd); return (EOF);}
  575.     max = (ptr = _bufend[fd] = _bufptr[fd]) + _bufsiz[fd];
  576.     do {         /* avoid DMA problem on physical 64K boundary */
  577.       if((max - ptr) < 512) chunk = max - ptr;
  578.       else                  chunk = 512;
  579.       ptr += (got = _bdos2(READ<<8, fd, chunk, ptr));
  580.       if(got < chunk) {_bufeof[fd] = YES; break;}
  581.       } while(ptr < max);
  582.     _bufend[fd] = ptr;
  583.     _bufnxt[fd] = _bufptr[fd];
  584.     _bufuse[fd] = IN;
  585.     }
  586.   }
  587.  
  588. /*
  589. ** Binary-Stream output of one byte to fd.
  590. */
  591. _write(ch, fd) int ch, fd; {
  592.   if(_bufuse[fd]) return(_writebuf(ch, fd));
  593.   if(_bdos2(WRITE<<8, fd, 1, &ch) != 1) {
  594.     _seterr(fd);
  595.     return (EOF);
  596.     }
  597.   return (ch);
  598.   }
  599.  
  600. /*
  601. ** Empty buffer if necessary, and store ch in buffer.
  602. */
  603. _writebuf(ch, fd) int ch, fd; {
  604.   char *ptr;
  605.   if(_bufuse[fd] == IN && _backup(fd)) return (EOF);
  606.   while(YES) {
  607.     ptr = _bufnxt[fd];
  608.     if(ptr < (_bufptr[fd] + _bufsiz[fd])) {
  609.       *ptr = ch;
  610.       ++_bufnxt[fd];
  611.       _bufuse[fd] = OUT;
  612.       return (ch&255);
  613.       }
  614.     if(_flush(fd)) return (EOF);
  615.     }
  616.   }
  617.  
  618. /*
  619. ** Flush buffer to DOS if dirty buffer.
  620. ** Reset buffer pointers in any case.
  621. */
  622. _flush(fd) int fd; {
  623.   int i, j, k, chunk;
  624.   if(_bufuse[fd] == OUT) {
  625.     i = _bufnxt[fd] - _bufptr[fd];
  626.     k = 0;
  627.     while(i > 0) {     /* avoid DMA problem on physical 64K boundary */
  628.       if(i < 512) chunk = i;
  629.       else        chunk = 512;
  630.       k += (j = _bdos2(WRITE<<8, fd, chunk, _bufptr[fd] + k));
  631.       if(j < chunk) {_seterr(fd); return (EOF);}
  632.       i -= j;
  633.       }
  634.     }
  635.   _empty(fd, YES);
  636.   return (NULL);
  637.   }
  638.  
  639. /*
  640. ** Adjust DOS file position to current point.
  641. */
  642. _adjust(fd) int fd; {
  643.   if(_bufuse[fd] == OUT) return (_flush(fd));
  644.   if(_bufuse[fd] == IN ) return (_backup(fd));
  645.   }
  646.  
  647. /*
  648. ** Backup DOS file position to current point.
  649. */
  650. _backup(fd) int fd; {
  651.   int hi, lo;
  652.   if(lo = _bufnxt[fd] - _bufend[fd]) {
  653.     hi = -1;
  654.     if(!_seek(FROM_CUR, fd, &hi, &lo)) {
  655.       _seterr(fd);
  656.       return (EOF);
  657.       }
  658.     }
  659.   _empty(fd, YES);
  660.   return (NULL);
  661.   }
  662.  
  663. /*
  664. ** Set buffer controls to empty status.
  665. */
  666. _empty(fd, mt) int fd, mt; {
  667.   _bufnxt[fd] = _bufend[fd] = _bufptr[fd];
  668.   _bufeof[fd] = NO;
  669.   if(mt) _bufuse[fd] = EMPTY;
  670.   }
  671.  
  672. /*
  673. ** Return fd's open mode, else NULL.
  674. */
  675. _mode(fd) char *fd; {
  676.   if(fd < MAXFILES) return (_status[fd]);
  677.   return (NULL);
  678.   }
  679.  
  680. /*
  681. ** Set eof status for fd and
  682. */
  683. _seteof(fd) int fd; {
  684.   _status[fd] |= EOFBIT;
  685.   }
  686.  
  687. /*
  688. ** Clear eof status for fd.
  689. */
  690. _clreof(fd) int fd; {
  691.   _status[fd] &= ~EOFBIT;
  692.   }
  693.  
  694. /*
  695. ** Set error status for fd.
  696. */
  697. _seterr(fd) int fd; {
  698.   _status[fd] |= ERRBIT;
  699.   }
  700.  
  701. /*
  702. ** Clear error status for fd.
  703. */
  704. _clrerr(fd) int fd; {
  705.   _status[fd] &= ~ERRBIT;
  706.   }
  707.  
  708. /*
  709. ** Allocate n bytes of (possibly zeroed) memory.
  710. ** Entry: n = Size of the items in bytes.
  711. **    clear = "true" if clearing is desired.
  712. ** Returns the address of the allocated block of memory
  713. ** or NULL if the requested amount of space is not available.
  714. */
  715. _alloc(n, clear) char *n; int clear; {
  716.   char *oldptr;
  717.   if(n < avail(YES)) {
  718.     if(clear) pad(_memptr, NULL, n);
  719.     oldptr = _memptr;
  720.     _memptr += n;
  721.     return (oldptr);
  722.     }
  723.   return (NULL);
  724.   }
  725.  
  726. /*
  727. ** Issue extended BDOS function and return result. 
  728. ** Entry: ax = function code and sub-function
  729. **        bx, cx, dx = other parameters
  730. */
  731. _bdos2(ax, bx, cx, dx) int ax, bx, cx, dx; {
  732. #asm
  733.   push bx         ; preserve secondary register
  734.   mov  dx,[bp+4]
  735.   mov  cx,[bp+6]
  736.   mov  bx,[bp+8]
  737.   mov  ax,[bp+10] ; load DOS function number
  738.   int  21h        ; call bdos
  739.   jnc  __bdos21   ; no error
  740.   neg  ax         ; make error code negative  
  741. __bdos21:
  742.   pop  bx         ; restore secondary register
  743. #endasm
  744.   }
  745.  
  746. /*
  747. ** Issue LSEEK call
  748. */
  749. _seek(org, fd, hi, lo) int org, fd, hi, lo; {
  750. #asm
  751.   push bx         ; preserve secondary register
  752.   mov  bx,[bp+4]
  753.   mov  dx,[bx]    ; get lo part of destination
  754.   mov  bx,[bp+6]
  755.   mov  cx,[bx]    ; get hi part of destination
  756.   mov  bx,[bp+8]  ; get file descriptor
  757.   mov  al,[bp+10] ; get origin code for seek
  758.   mov  ah,42h     ; move-file-pointer function
  759.   int  21h        ; call bdos
  760.   jnc  __seek1    ; error?
  761.   xor  ax,ax      ; yes, return false
  762.   jmp  __seek2 
  763. __seek1:          ; no, set hi and lo
  764.   mov  bx,[bp+4]  ; get address of lo
  765.   mov  [bx],ax    ; store low part of new position
  766.   mov  bx,[bp+6]  ; get address of hi
  767.   mov  [bx],dx    ; store high part of new position
  768.   mov  ax,1       ; return true
  769. __seek2:
  770.   pop  bx         ; restore secondary register
  771. #endasm
  772.   }
  773.  
  774. /*
  775. ** Test for keyboard input
  776. */
  777. _hitkey() {
  778. #asm
  779.   mov  ah,1       ; sub-service = test keyboard
  780.   int  16h        ; call bdos keyboard services
  781.   jnz  __hit1
  782.   xor ax,ax       ; nothing there, return false
  783.   jmp  __hit2
  784. __hit1:
  785.   mov  ax,1       ; character ready, return true
  786. __hit2:
  787. #endasm
  788.   }
  789.  
  790. /*
  791. ** Return next keyboard character
  792. */
  793. _getkey() {
  794. #asm
  795.   mov  ah,0       ; sub-service = read keyboard
  796.   int  16h        ; call bdos keyboard services
  797.   or   al,al      ; special character?
  798.   jnz  __get2     ; no
  799.   mov  al,ah      ; yes, move it to al
  800.   cmp  al,3       ; ctl-2 (simulated null)?
  801.   jne  __get1     ; no
  802.   xor  al,al      ; yes, report zero
  803.   jmp  __get2
  804. __get1:
  805.   add  al,113     ; offset to range 128-245
  806. __get2:
  807.   xor  ah,ah      ; zero ah
  808. #endasm
  809.   }
  810.  
  811. >>> CTELL.C 613
  812. #define NOCCARGC  /* no arg count passing */
  813. #include "stdio.h"
  814. #include "clib.def"
  815. extern int _bufuse[];
  816. /*
  817. ** Return offset to current 128-byte record.
  818. */
  819. ctell(fd) int fd; {
  820.   int hi, lo;
  821.   if(!_mode(fd) || !_bufuse[fd]) return (-1);
  822.   if(_adjust(fd)) return (-1);
  823.   hi = lo = 0;
  824.   _seek(FROM_CUR, fd, &hi, &lo);
  825.   return ((hi << 9) | ((lo >> 7) & 511));
  826.   }
  827.  
  828. /*
  829. ** Return offset to next byte in current 128-byte record.
  830. */
  831. ctellc(fd) int fd; {
  832.   int hi, lo;
  833.   if(!_mode(fd) || !_bufuse[fd]) return (-1);
  834.   if(_adjust(fd)) return (-1);
  835.   hi = lo = 0;
  836.   _seek(FROM_CUR, fd, &hi, &lo);
  837.   return (lo & 127);
  838.   }
  839.  
  840. >>> DTOI.C 420
  841. #define NOCCARGC  /* no argument count passing */
  842. #include "stdio.h"
  843. /*
  844. ** dtoi -- convert signed decimal string to integer nbr
  845. **         returns field length, else ERR on error
  846. */
  847. dtoi(decstr, nbr)  char *decstr;  int *nbr;  {
  848.   int len, s;
  849.   if((*decstr)=='-') {s=1; ++decstr;} else s=0;
  850.   if((len=utoi(decstr, nbr))<0) return ERR;
  851.   if(*nbr<0) return ERR;
  852.   if(s) {*nbr = -*nbr; return ++len;} else return len;
  853.   }
  854.  
  855. >>> EXIT.C 501
  856. #define NOCCARGC  /* no argument count passing */
  857. #include "stdio.h"
  858. #include "clib.def"
  859. /*
  860. ** Close all open files and exit to DOS. 
  861. ** Entry: ec = exit code.
  862. */
  863. exit(ec) int ec; {
  864.   int fd;  char str[4];
  865.   ec &= 255;
  866.   if(ec) {
  867.     left(itou(ec, str, 4));
  868.     fputs("\7Exit Code: ", stderr);
  869.     fputs(str, stderr);
  870.     fputs("\n", stderr);
  871.     }
  872.   for(fd = 0; fd < MAXFILES; ++fd) fclose(fd);
  873.   _bdos2((RETDOS<<8)|ec, NULL, NULL, NULL);
  874. #asm
  875. _abort: jmp    _exit
  876.         public _abort
  877. #endasm
  878.   }
  879.  
  880. >>> FCLOSE.C 388
  881. #define NOCCARGC  /* no argument count passing */
  882. #include "stdio.h"
  883. #include "clib.def"
  884. /*
  885. ** Close fd 
  886. ** Entry: fd = file descriptor for file to be closed.
  887. ** Returns NULL for success, otherwise ERR
  888. */
  889. extern int _status[];
  890. fclose(fd) int fd; {
  891.   if(!_mode(fd) || _flush(fd)) return (ERR);
  892.   if(_bdos2(CLOSE<<8, fd, NULL, NULL) == -6) return (ERR);
  893.   return (_status[fd] = NULL);
  894.   }
  895.  
  896. >>> FEOF.C 266
  897. #define NOCCARGC  /* no argument count passing */
  898. #include "clib.def"
  899. extern int _status[];
  900. /*
  901. ** Test for end-of-file status.
  902. ** Entry: fd = file descriptor
  903. ** Returns non-zero if fd is at eof, else zero.
  904. */
  905. feof(fd) int fd; {
  906.   return (_status[fd] & EOFBIT);
  907.   }
  908.  
  909. >>> FERROR.C 199
  910. #define NOCCARGC  /* no arg count passing */
  911. #include "stdio.h"
  912. #include "clib.def"
  913. extern _status[];
  914. /*
  915. ** Test for error status on fd.
  916. */
  917. ferror(fd) int fd; {
  918.   return (_status[fd] & ERRBIT);
  919.   }
  920.  
  921. >>> FGETC.C 841
  922. #define NOCCARGC  /* no argument count passing */
  923. #include "stdio.h"
  924. #include "clib.def"
  925. /*
  926. ** Character-stream input of one character from fd.
  927. ** Entry: fd = File descriptor of pertinent file.
  928. ** Returns the next character on success, else EOF.
  929. */
  930. fgetc(fd) int fd; {
  931.   int ch;
  932.   while(1) {
  933.     if(iscons(fd)) {
  934.       switch(ch = _getkey()) {
  935.         case ABORT: exit(7);
  936.         case    LF:
  937.         case    CR: _write(CR, stderr); _write(LF, stderr); break;
  938.         case   DEL: ch = RUB;
  939.         case   RUB:
  940.         case  WIPE: break;
  941.         default:    _write(ch, stderr);
  942.         }
  943.       }
  944.     else ch = _read(fd);
  945.     switch(ch) {
  946.       default: return (ch);
  947.       case DOSEOF: _seteof(fd); return (EOF);
  948.       case     CR: return ('\n');
  949.       case     LF:
  950.       }
  951.     }
  952.   }
  953. #asm
  954. _getc:  jmp     _fgetc
  955.         public  _getc
  956. #endasm
  957.  
  958. >>> FGETS.C 1696
  959. #define NOCCARGC  /* no arg count passing */
  960. #include "stdio.h"
  961. #include "clib.def"
  962. /*
  963. ** Gets an entire string (including its newline
  964. ** terminator) or size-1 characters, whichever comes
  965. ** first. The input is terminated by a null character.
  966. ** Entry: str  = Pointer to destination buffer.
  967. **        size = Size of the destination buffer.
  968. **        fd   = File descriptor of pertinent file.
  969. ** Returns str on success, else NULL.
  970. */
  971. fgets(str, size, fd) char *str; int size, fd; {
  972.   return (_gets(str, size, fd, 1));
  973.   }
  974.  
  975. /*
  976. ** Gets an entire string from stdin (excluding its newline
  977. ** terminator) or size-1 characters, whichever comes
  978. ** first. The input is terminated by a null character.
  979. ** The user buffer must be large enough to hold the data.
  980. ** Entry: str  = Pointer to destination buffer.
  981. ** Returns str on success, else NULL.
  982. */
  983. gets(str) char *str; {
  984.   return (_gets(str, 32767, stdin, 0));
  985.   }
  986.  
  987. _gets(str, size, fd, nl) char *str; int size, fd, nl; {
  988.   int backup; char *next;
  989.   next = str;
  990.   while(--size > 0) {
  991.     switch (*next = fgetc(fd)) {
  992.       case  EOF: *next = NULL;
  993.                  if(next == str) return (NULL);
  994.                  return (str);
  995.       case '\n': *(next + nl) = NULL;
  996.                  return (str);
  997.       case  RUB: if(next > str) backup = 1; else backup = 0;
  998.                  goto backout;
  999.       case WIPE: backup = next - str;
  1000.         backout: if(iscons(fd)) {
  1001.                    ++size;
  1002.                    while(backup--) {
  1003.                      fputs("\b \b", stderr);
  1004.                      --next; ++size;
  1005.                      }
  1006.                    continue;
  1007.                    }
  1008.         default: ++next;
  1009.       }
  1010.     }
  1011.   *next = NULL;
  1012.   return (str);
  1013.   }
  1014.  
  1015. >>> FOPEN.C 532
  1016. #define NOCCARGC  /* no arg count passing */
  1017. #include "stdio.h"
  1018. #include "clib.def"
  1019. /*
  1020. ** Open file indicated by fn.
  1021. ** Entry: fn   = Null-terminated DOS file name.
  1022. **        mode = "a"  - append
  1023. **               "r"  - read
  1024. **               "w"  - write
  1025. **               "a+" - append update
  1026. **               "r+" - read   update
  1027. **               "w+" - write  update
  1028. ** Returns a file descriptor on success, else NULL.
  1029. */
  1030. fopen(fn, mode) char *fn, *mode; {
  1031.   int fd;
  1032.   if(!_open(fn, mode, &fd)) return (NULL);
  1033.   return (fd);
  1034.   }
  1035.  
  1036. >>> FPRINTF.C 2277
  1037. #define NOCCARGC 
  1038. /*
  1039. ** Yes, that is correct.  Although these functions use an
  1040. ** argument count, they do not call functions which need one.
  1041. */
  1042. #include "stdio.h"
  1043. /*
  1044. ** fprintf(fd, ctlstring, arg, arg, ...) - Formatted print.
  1045. ** Operates as described by Kernighan & Ritchie.
  1046. ** b, c, d, o, s, u, and x specifications are supported.
  1047. ** Note: b (binary) is a non-standard extension.
  1048. */
  1049. fprintf(argc) int argc; {
  1050.   int *nxtarg;
  1051.   nxtarg = CCARGC() + &argc;
  1052.   return(_print(*(--nxtarg), --nxtarg));
  1053.   }
  1054.  
  1055. /*
  1056. ** printf(ctlstring, arg, arg, ...) - Formatted print.
  1057. ** Operates as described by Kernighan & Ritchie.
  1058. ** b, c, d, o, s, u, and x specifications are supported.
  1059. ** Note: b (binary) is a non-standard extension.
  1060. */
  1061. printf(argc) int argc; {
  1062.   return(_print(stdout, CCARGC() + &argc - 1));
  1063.   }
  1064.  
  1065. /*
  1066. ** _print(fd, ctlstring, arg, arg, ...)
  1067. ** Called by fprintf() and printf().
  1068. */
  1069. _print(fd, nxtarg) int fd, *nxtarg; {
  1070.   int  arg, left, pad, cc, len, maxchr, width;
  1071.   char *ctl, *sptr, str[17];
  1072.   cc = 0;                                         
  1073.   ctl = *nxtarg--;                          
  1074.   while(*ctl) {
  1075.     if(*ctl!='%') {fputc(*ctl++, fd); ++cc; continue;}
  1076.     else ++ctl;
  1077.     if(*ctl=='%') {fputc(*ctl++, fd); ++cc; continue;}
  1078.     if(*ctl=='-') {left = 1; ++ctl;} else left = 0;       
  1079.     if(*ctl=='0') pad = '0'; else pad = ' ';           
  1080.     if(isdigit(*ctl)) {
  1081.       width = atoi(ctl++);
  1082.       while(isdigit(*ctl)) ++ctl;
  1083.       }
  1084.     else width = 0;
  1085.     if(*ctl=='.') {            
  1086.       maxchr = atoi(++ctl);
  1087.       while(isdigit(*ctl)) ++ctl;
  1088.       }
  1089.     else maxchr = 0;
  1090.     arg = *nxtarg--;
  1091.     sptr = str;
  1092.     switch(*ctl++) {
  1093.       case 'c': str[0] = arg; str[1] = NULL; break;
  1094.       case 's': sptr = arg;        break;
  1095.       case 'd': itoa(arg,str);     break;
  1096.       case 'b': itoab(arg,str,2);  break;
  1097.       case 'o': itoab(arg,str,8);  break;
  1098.       case 'u': itoab(arg,str,10); break;
  1099.       case 'x': itoab(arg,str,16); break;
  1100.       default:  return (cc);
  1101.       }
  1102.     len = strlen(sptr);
  1103.     if(maxchr && maxchr<len) len = maxchr;
  1104.     if(width>len) width = width - len; else width = 0; 
  1105.     if(!left) while(width--) {fputc(pad,fd); ++cc;}
  1106.     while(len--) {fputc(*sptr++,fd); ++cc; }
  1107.     if(left) while(width--) {fputc(pad,fd); ++cc;}  
  1108.     }
  1109.   return(cc);
  1110.   }
  1111.  
  1112. >>> FPUTC.C 591
  1113. #define NOCCARGC  /* no arg count passing */
  1114. #include "stdio.h"
  1115. #include "clib.def"
  1116. extern int _status[];
  1117. /*
  1118. ** Character-stream output of a character to fd.
  1119. ** Entry: ch = Character to write.
  1120. **        fd = File descriptor of perinent file.
  1121. ** Returns character written on success, else EOF.
  1122. */
  1123. fputc(ch, fd) int ch, fd; {
  1124.   switch(ch) {
  1125.     case  EOF: _write(DOSEOF, fd); break;
  1126.     case '\n': _write(CR, fd); _write(LF, fd); break;
  1127.     default:   _write(ch, fd);
  1128.     }
  1129.   if(_status[fd] & ERRBIT) return (EOF);
  1130.   return (ch);
  1131.   }
  1132. #asm
  1133. _putc:  jmp     _fputc
  1134.         public  _putc
  1135. #endasm
  1136.  
  1137. >>> FPUTS.C 310
  1138. #define NOCCARGC  /* no arg count passing */
  1139. #include "stdio.h"
  1140. #include "clib.def"
  1141. /*
  1142. ** Write a string to fd. 
  1143. ** Entry: string = Pointer to null-terminated string.
  1144. **        fd     = File descriptor of pertinent file.
  1145. */
  1146. fputs(string,fd) char *string; int fd; {
  1147.   while(*string) fputc(*string++, fd) ;
  1148.   }
  1149.  
  1150. >>> FREAD.C 929
  1151. #define NOCCARGC  /* no argument count passing */
  1152. #include "clib.def"
  1153. extern int _status[];
  1154. /*
  1155. ** Item-stream read from fd.
  1156. ** Entry: buf = address of target buffer
  1157. **         sz = size of items in bytes
  1158. **          n = number of items to read
  1159. **         fd = file descriptor
  1160. ** Returns a count of the items actually read.
  1161. ** Use feof() and ferror() to determine file status.
  1162. */
  1163. fread(buf, sz, n, fd) char *buf; int sz, n, fd; {
  1164.   return (read(fd, buf, n*sz)/sz);
  1165.   }
  1166.  
  1167. /*
  1168. ** Binary-stream read from fd.
  1169. ** Entry:  fd = file descriptor
  1170. **        buf = address of target buffer
  1171. **          n = number of bytes to read
  1172. ** Returns a count of the bytes actually read.
  1173. ** Use feof() and ferror() to determine file status.
  1174. */
  1175. read(fd, buf, n) int fd, n; char *buf; {
  1176.   char *cnt;  /* fake unsigned */
  1177.   cnt = 0;
  1178.   while(n--) {
  1179.     *buf++ = _read(fd);
  1180.     if(_status[fd] & (ERRBIT | EOFBIT)) break;
  1181.     ++cnt;
  1182.     }
  1183.   return (cnt);
  1184.   }
  1185.  
  1186. >>> FREE.C 424
  1187. #define NOCCARGC  /* no argument count passing */
  1188. extern char *_memptr;
  1189. /*
  1190. ** free(ptr) - Free previously allocated memory block.
  1191. ** Memory must be freed in the reverse order from which
  1192. ** it was allocated.
  1193. ** ptr    = Value returned by calloc() or malloc().
  1194. ** Returns ptr if successful or NULL otherwise.
  1195. */
  1196. free(ptr) char *ptr; {
  1197.    return (_memptr = ptr);
  1198.    }
  1199. #asm
  1200. _cfree: jmp     _free
  1201.         public  _cfree
  1202. #endasm
  1203.  
  1204. >>> FREOPEN.C 851
  1205. #define NOCCARGC  /* no argument count passing */
  1206. #include <stdio.h>
  1207. #include "clib.def"
  1208. /*
  1209. ** Close previously opened fd and reopen it. 
  1210. ** Entry: fn   = Null-terminated DOS file name.
  1211. **        mode = "a"  - append
  1212. **               "r"  - read
  1213. **               "w"  - write
  1214. **               "a+" - append update
  1215. **               "r+" - read   update
  1216. **               "w+" - write  update
  1217. **        fd   = File descriptor of pertinent file.
  1218. ** Returns the original fd on success, else NULL.
  1219. */
  1220. extern int _status[];
  1221. freopen(fn, mode, fd) char *fn, *mode; int fd; {
  1222.   int tfd;
  1223.   if(fclose(fd)) return (NULL);
  1224.   if(!_open(fn, mode, &tfd)) return (NULL);
  1225.   if(fd != tfd) {
  1226.     if(_bdos2(FORCE<<8, tfd, fd, NULL) < 0) return (NULL);
  1227.     _status[fd] = _status[tfd];
  1228.     _status[tfd] = 0;       /* leaves DOS using two handles */
  1229.     }
  1230.   return (fd);
  1231.   }
  1232.  
  1233. >>> FSCANF.C 2687
  1234. #define NOCCARGC  /* no argument count passing */
  1235. /*
  1236. ** Yes, that is correct.  Although these functions use an
  1237. ** argument count, they do not call functions which need one.
  1238. */
  1239. #include "stdio.h"
  1240. /*
  1241. ** fscanf(fd, ctlstring, arg, arg, ...) - Formatted read.
  1242. ** Operates as described by Kernighan & Ritchie.
  1243. ** b, c, d, o, s, u, and x specifications are supported.
  1244. ** Note: b (binary) is a non-standard extension.
  1245. */
  1246. fscanf(argc) int argc; {
  1247.   int *nxtarg;
  1248.   nxtarg = CCARGC() + &argc;
  1249.   return (_scan(*(--nxtarg), --nxtarg));
  1250.   }
  1251.  
  1252. /*
  1253. ** scanf(ctlstring, arg, arg, ...) - Formatted read.
  1254. ** Operates as described by Kernighan & Ritchie.
  1255. ** b, c, d, o, s, u, and x specifications are supported.
  1256. ** Note: b (binary) is a non-standard extension.
  1257. */
  1258. scanf(argc) int argc; {
  1259.   return (_scan(stdin, CCARGC() + &argc - 1));
  1260.   }
  1261.  
  1262. /*
  1263. ** _scan(fd, ctlstring, arg, arg, ...) - Formatted read.
  1264. ** Called by fscanf() and scanf().
  1265. */
  1266. _scan(fd,nxtarg) int fd, *nxtarg; {
  1267.   char *carg, *ctl, *unsigned;
  1268.   int  *narg, wast, ac, width, ch, cnv, base, ovfl, sign;
  1269.   ac = 0;
  1270.   ctl = *nxtarg--;
  1271.   while(*ctl) {
  1272.     if(isspace(*ctl)) {++ctl; continue;}
  1273.     if(*ctl++ != '%') continue;
  1274.     if(*ctl == '*') {narg = carg = &wast; ++ctl;}
  1275.     else             narg = carg = *nxtarg--;
  1276.     ctl += utoi(ctl, &width);
  1277.     if(!width) width = 32767;
  1278.     if(!(cnv = *ctl++)) break;
  1279.     while(isspace(ch = fgetc(fd))) ;
  1280.     if(ch == EOF) {if(ac) break; else return(EOF);}
  1281.     ungetc(ch,fd);
  1282.     switch(cnv) {
  1283.       case 'c':
  1284.         *carg = fgetc(fd);
  1285.         break;
  1286.       case 's':
  1287.         while(width--) {
  1288.           if((*carg = fgetc(fd)) == EOF) break;
  1289.           if(isspace(*carg)) break;
  1290.           if(carg != &wast) ++carg;
  1291.           }
  1292.         *carg = 0;
  1293.         break;
  1294.       default:
  1295.         switch(cnv) {
  1296.           case 'b': base =  2; sign = 1; ovfl = 32767; break;
  1297.           case 'd': base = 10; sign = 0; ovfl =  3276; break;
  1298.           case 'o': base =  8; sign = 1; ovfl =  8191; break;
  1299.           case 'u': base = 10; sign = 1; ovfl =  6553; break;
  1300.           case 'x': base = 16; sign = 1; ovfl =  4095; break;
  1301.           default:  return (ac);
  1302.           }
  1303.         *narg = unsigned = 0;
  1304.         while(width-- && !isspace(ch=fgetc(fd)) && ch!=EOF) {
  1305.           if(!sign)
  1306.             if(ch == '-') {sign = -1; continue;}
  1307.             else sign = 1;
  1308.           if(ch < '0') return (ac);
  1309.           if(ch >= 'a')      ch -= 87;
  1310.           else if(ch >= 'A') ch -= 55;
  1311.           else               ch -= '0';
  1312.           if(ch >= base || unsigned > ovfl) return (ac);
  1313.           unsigned = unsigned * base + ch;
  1314.           }
  1315.         *narg = sign * unsigned;
  1316.       }
  1317.     ++ac;                          
  1318.     }
  1319.   return (ac);
  1320.   }
  1321.  
  1322. >>> FWRITE.C 1001
  1323. #define NOCCARGC  /* no argument count passing */
  1324. #include "clib.def"
  1325. extern int _status[];
  1326. /*
  1327. ** Item-stream write to fd.
  1328. ** Entry: buf = address of source buffer
  1329. **         sz = size of items in bytes
  1330. **          n = number of items to write
  1331. **         fd = file descriptor
  1332. ** Returns a count of the items actually written or
  1333. ** zero if an error occurred.
  1334. ** May use ferror(), as always, to detect errors.
  1335. */
  1336. fwrite(buf, sz, n, fd) char *buf; int sz, n, fd; {
  1337.   if(write(fd, buf, n*sz) == -1) return (0);
  1338.   return (n);
  1339.   }
  1340.  
  1341. /*
  1342. ** Binary-stream write to fd.
  1343. ** Entry:  fd = file descriptor
  1344. **        buf = address of source buffer
  1345. **          n = number of bytes to write
  1346. ** Returns a count of the bytes actually written or
  1347. ** -1 if an error occurred.
  1348. ** May use ferror(), as always, to detect errors.
  1349. */
  1350. write(fd, buf, n) int fd, n; char *buf; {
  1351.   char *cnt;  /* fake unsigned */
  1352.   cnt = n;
  1353.   while(cnt--) {
  1354.     _write(*buf++, fd);
  1355.     if(_status[fd] & ERRBIT) return (-1);
  1356.     }
  1357.   return (n);
  1358.   }
  1359.  
  1360. >>> GETARG.C 672
  1361. #define NOCCARGC  /* no argument count passing */
  1362. #include "stdio.h"
  1363. /*
  1364. ** Get command line argument. 
  1365. ** Entry: n    = Number of the argument.
  1366. **        s    = Destination string pointer.
  1367. **        size = Size of destination string.
  1368. **        argc = Argument count from main().
  1369. **        argv = Argument vector(s) from main().
  1370. ** Returns number of characters moved on success,
  1371. ** else EOF.
  1372. */
  1373. getarg(n,s,size,argc,argv)
  1374.   int n; char *s; int size, argc, argv[]; {
  1375.   char *str;
  1376.   int i;
  1377.   if(n < 0 | n >= argc) {
  1378.     *s = NULL;
  1379.     return EOF;
  1380.     }
  1381.   i = 0;
  1382.   str=argv[n];
  1383.   while(i<size) {
  1384.     if((s[i]=str[i])==NULL) break;
  1385.     ++i;
  1386.     }
  1387.   s[i]=NULL;
  1388.   return i;
  1389.   }
  1390.  
  1391. >>> GETCHAR.C 161
  1392. #define NOCCARGC  /* no argument count passing */
  1393. #include "stdio.h"
  1394. /*
  1395. ** Get next character from standard input. 
  1396. */
  1397. getchar() {
  1398.   return (fgetc(stdin));
  1399.   }
  1400.  
  1401. >>> ISALNUM.C 174
  1402. /*
  1403. ** return 'true' if c is alphanumeric
  1404. */
  1405. isalnum(c) int c; {
  1406.   int yesno;
  1407.   yesno = (c<='z' && c>='a');
  1408.   return (yesno || (c<='Z' && c>='A') || (c<='9' && c>='0'));
  1409.   }
  1410.  
  1411. >>> ISALPHA.C 120
  1412. /*
  1413. ** return 'true' if c is alphabetic
  1414. */
  1415. isalpha(c) int c; {
  1416.   return ((c<='z' && c>='a') || (c<='Z' && c>='A'));
  1417.   }
  1418.  
  1419. >>> ISASCII.C 148
  1420. /*
  1421. ** return 'true' if c is an ASCII character (0-127)
  1422. */
  1423. isascii(c) char *c; {
  1424.   /* c is a simulated unsigned integer */
  1425.   return (c <= 127);
  1426.   }
  1427.  
  1428. >>> ISATTY.C 374
  1429. /*
  1430. ** Return "true" if fd is a device, else "false"
  1431. */
  1432. isatty(fd) int fd; {
  1433. fd;               /* fetch handle */
  1434. #asm
  1435.   push bx         ; save 2nd reg
  1436.   mov  bx,ax      ; place handle
  1437.   mov  ax,4400h   ; ioctl get info function
  1438.   int 21h         ; call BDOS
  1439.   pop  bx         ; restore 2nd reg
  1440.   mov  ax,dx      ; fetch info bits
  1441.   and  ax,80h     ; isdev bit
  1442. #endasm
  1443.   }
  1444.  
  1445.  
  1446. >>> ISCNTRL.C 173
  1447. /*
  1448. ** return 'true' if c is a control character
  1449. ** (0-31 or 127)
  1450. */
  1451. iscntrl(c) char *c; {
  1452.   /* c is a simulated unsigned integer */
  1453.   return ((c <= 31) || (c == 127));
  1454.   }
  1455.  
  1456. >>> ISCONS.C 501
  1457. /*
  1458. ** Determine if fd is the console.
  1459. */
  1460. iscons(fd) int fd; {
  1461. fd;               /* fetch handle */
  1462. #asm
  1463.   push bx         ; save 2nd reg
  1464.   mov  bx,ax      ; place handle
  1465.   mov  ax,4400h   ; ioctl get info function
  1466.   int 21h         ; call BDOS
  1467.   pop  bx         ; restore 2nd reg
  1468.   mov  ax,dx      ; fetch info bits
  1469.   and  ax,83h     ; keep device and console bits
  1470.   cmp  ax,80h     ; device and console?
  1471.   jg   __cons1
  1472.   xor  ax,ax      ; return false if not device and console
  1473. __cons1:
  1474. #endasm
  1475.   }
  1476.  
  1477. >>> ISDIGIT.C 101
  1478. /*
  1479. ** return 'true' if c is a decimal digit
  1480. */
  1481. isdigit(c) int c; {
  1482.   return (c<='9' && c>='0');
  1483.   }
  1484.  
  1485. >>> ISGRAPH.C 116
  1486. /*
  1487. ** return 'true' if c is a graphic character
  1488. ** (33-126)
  1489. */
  1490. isgraph(c) int c; {
  1491.   return (c>=33 && c<=126);
  1492.   }
  1493.  
  1494. >>> ISLOWER.C 107
  1495. /*
  1496. ** return 'true' if c is lower-case alphabetic
  1497. */
  1498. islower(c) int c; {
  1499.   return (c<='z' && c>='a');
  1500.   }
  1501.  
  1502. >>> ISPRINT.C 118
  1503. /*
  1504. ** return 'true' if c is a printable character
  1505. ** (32-126)
  1506. */
  1507. isprint(c) int c; {
  1508.   return (c>=32 && c<=126);
  1509.   }
  1510.  
  1511. >>> ISPUNCT.C 207
  1512. #define NOCCARGC  /* no argument count passing */
  1513. /*
  1514. ** return 'true' if c is a punctuation character
  1515. ** (all but control and alphanumeric)
  1516. */
  1517. ispunct(c) int c; {
  1518.   return (!isalnum(c) && !iscntrl(c));
  1519.   }
  1520.  
  1521. >>> ISSPACE.C 180
  1522. /*
  1523. ** return 'true' if c is a white-space character
  1524. */
  1525. isspace(c) int c; {
  1526.   /* first check gives quick exit in most cases */
  1527.   return(c<=' ' && (c==' ' || (c<=13 && c>=9)));
  1528.   }
  1529.  
  1530. >>> ISUPPER.C 107
  1531. /*
  1532. ** return 'true' if c is upper-case alphabetic
  1533. */
  1534. isupper(c) int c; {
  1535.   return (c<='Z' && c>='A');
  1536.   }
  1537.  
  1538. >>> ISXDIGIT.C 205
  1539. /*
  1540. ** return 'true' if c is a hexadecimal digit
  1541. ** (0-9, A-F, or a-f)
  1542. */
  1543. isxdigit(c) int c; {
  1544.   int yesno;
  1545.   yesno = (c<='f' && c>='a');
  1546.   return ( yesno || (c<='F' && c>='A') || (c<='9' && c>='0'));
  1547.   }
  1548.  
  1549. >>> ITOA.C 326
  1550. #define NOCCARGC  /* no argument count passing */
  1551. /*
  1552. ** itoa(n,s) - Convert n to characters in s 
  1553. */
  1554. itoa(n, s) char *s; int n; {
  1555.   int sign;
  1556.   char *ptr;
  1557.   ptr = s;
  1558.   if ((sign = n) < 0) n = -n;
  1559.   do {
  1560.     *ptr++ = n % 10 + '0';
  1561.     } while ((n = n / 10) > 0);
  1562.   if (sign < 0) *ptr++ = '-';
  1563.   *ptr = '\0';
  1564.   reverse(s);
  1565.   }
  1566.  
  1567. >>> ITOAB.C 475
  1568. #define NOCCARGC  /* no argument count passing */
  1569. /*
  1570. ** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b.
  1571. **                NOTE: This is a non-standard function.
  1572. */
  1573. itoab(n, s, b) int n; char *s; int b; {
  1574.   char *ptr;
  1575.   int lowbit;
  1576.   ptr = s;
  1577.   b >>= 1;
  1578.   do {
  1579.     lowbit = n & 1;
  1580.     n = (n >> 1) & 32767;
  1581.     *ptr = ((n % b) << 1) + lowbit;
  1582.     if(*ptr < 10) *ptr += '0'; else *ptr += 55;
  1583.     ++ptr;
  1584.     } while(n /= b);
  1585.   *ptr = 0;
  1586.   reverse (s);
  1587.   }
  1588.  
  1589. >>> ITOD.C 623
  1590. #include "stdio.h"
  1591. /*
  1592. ** itod -- convert nbr to signed decimal string of width sz
  1593. **         right adjusted, blank filled; returns str
  1594. **
  1595. **        if sz > 0 terminate with null byte
  1596. **        if sz = 0 find end of string
  1597. **        if sz < 0 use last byte for data
  1598. */
  1599. itod(nbr, str, sz)  int nbr;  char str[];  int sz;  {
  1600.   char sgn;
  1601.   if(nbr<0) {nbr = -nbr; sgn='-';}
  1602.   else sgn=' ';
  1603.   if(sz>0) str[--sz]=NULL;
  1604.   else if(sz<0) sz = -sz;
  1605.   else while(str[sz]!=NULL) ++sz;
  1606.   while(sz) {
  1607.     str[--sz]=(nbr%10+'0');
  1608.     if((nbr=nbr/10)==0) break;
  1609.     }
  1610.   if(sz) str[--sz]=sgn;
  1611.   while(sz>0) str[--sz]=' ';
  1612.   return str;
  1613.   }
  1614.  
  1615. >>> ITOO.C 541
  1616. /*
  1617. ** itoo -- converts nbr to octal string of length sz
  1618. **         right adjusted and blank filled, returns str
  1619. **
  1620. **        if sz > 0 terminate with null byte
  1621. **        if sz = 0 find end of string
  1622. **        if sz < 0 use last byte for data
  1623. */
  1624. itoo(nbr, str, sz)  int nbr;  char str[];  int sz;  {
  1625.   int digit;
  1626.   if(sz>0) str[--sz]=0;
  1627.   else if(sz<0) sz = -sz;
  1628.   else while(str[sz]!=0) ++sz;
  1629.   while(sz) {
  1630.     digit=nbr&7; nbr=(nbr>>3)&8191;
  1631.     str[--sz]=digit+48;
  1632.     if(nbr==0) break;
  1633.     }
  1634.   while(sz) str[--sz]=' ';
  1635.   return str;
  1636.   }
  1637.  
  1638. >>> ITOU.C 621
  1639. #include "stdio.h"
  1640. /*
  1641. ** itou -- convert nbr to unsigned decimal string of width sz
  1642. **         right adjusted, blank filled; returns str
  1643. **
  1644. **        if sz > 0 terminate with null byte
  1645. **        if sz = 0 find end of string
  1646. **        if sz < 0 use last byte for data
  1647. */
  1648. itou(nbr, str, sz)  int nbr;  char str[];  int sz;  {
  1649.   int lowbit;
  1650.   if(sz>0) str[--sz]=NULL;
  1651.   else if(sz<0) sz = -sz;
  1652.   else while(str[sz]!=NULL) ++sz;
  1653.   while(sz) {
  1654.     lowbit=nbr&1;
  1655.     nbr=(nbr>>1)&32767;  /* divide by 2 */
  1656.     str[--sz]=((nbr%5)<<1)+lowbit+'0';
  1657.     if((nbr=nbr/5)==0) break;
  1658.     }
  1659.   while(sz) str[--sz]=' ';
  1660.   return str;
  1661.   }
  1662.  
  1663. >>> ITOX.C 596
  1664. /*
  1665. ** itox -- converts nbr to hex string of length sz
  1666. **         right adjusted and blank filled, returns str
  1667. **
  1668. **        if sz > 0 terminate with null byte
  1669. **        if sz = 0 find end of string
  1670. **        if sz < 0 use last byte for data
  1671. */
  1672. itox(nbr, str, sz)  int nbr;  char str[];  int sz;  {
  1673.   int digit, offset;
  1674.   if(sz>0) str[--sz]=0;
  1675.   else if(sz<0) sz = -sz;
  1676.   else while(str[sz]!=0) ++sz;
  1677.   while(sz) {
  1678.     digit=nbr&15; nbr=(nbr>>4)&4095;
  1679.     if(digit<10) offset=48; else offset=55;
  1680.     str[--sz]=digit+offset;
  1681.     if(nbr==0) break;
  1682.     }
  1683.   while(sz) str[--sz]=' ';
  1684.   return str;
  1685.   }
  1686.  
  1687. >>> LEFT.C 166
  1688. /*
  1689. ** left -- left adjust and null terminate a string
  1690. */
  1691. left(str) char *str; {
  1692.   char *str2;
  1693.   str2=str;
  1694.   while(*str2==' ') ++str2;
  1695.   while(*str++ = *str2++);
  1696.   }
  1697.  
  1698. >>> LEXCMP.C 1363
  1699. #define NOCCARGC  /* no argument count passing */
  1700. /*
  1701. ** lexcmp(s, t) - Return a number <0, 0, or >0
  1702. **                as s is <, =, or > t.
  1703. */
  1704. lexcmp(s, t) char *s, *t; {
  1705.   while(lexorder(*s, *t) == 0)
  1706.     if(*s++) ++t;
  1707.     else return (0);
  1708.   return (lexorder(*s, *t));
  1709.   }
  1710.  
  1711. /*
  1712. ** lexorder(c1, c2)
  1713. **
  1714. ** Return a negative, zero, or positive number if
  1715. ** c1 is less than, equal to, or greater than c2,
  1716. ** based on a lexicographical (dictionary order)
  1717. ** colating sequence.
  1718. **
  1719. */
  1720. char _lex[128] = {
  1721.      /**** NUL - / ****/
  1722.        0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
  1723.       10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
  1724.       20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  1725.       30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
  1726.       40, 41, 42, 43, 44, 45, 46, 47,
  1727.      /**** 0-9 ****/
  1728.       65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
  1729.      /**** : ; < = > ? @ ****/
  1730.       48, 49, 50, 51, 52, 53, 54,
  1731.      /**** A-Z ****/
  1732.       75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
  1733.       88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,
  1734.      /**** [ \ ] ^ _ ` ****/
  1735.       55, 56, 57, 58, 59, 60,
  1736.      /**** a-z ****/
  1737.       75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
  1738.       88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,
  1739.      /**** { | } ~ ****/
  1740.       61, 62, 63, 64,
  1741.      /**** DEL ****/
  1742.      127
  1743.      };
  1744.  
  1745. lexorder(c1, c2) char c1, c2; {
  1746.   return(_lex[c1] - _lex[c2]);
  1747.   }
  1748.  
  1749. >>> LINK.ASM 137
  1750.         extrn   __main: near
  1751. code    segment public
  1752.         assume  cs:code
  1753.         public  __link
  1754. __link: nop
  1755. code    ends
  1756.         end
  1757.  
  1758. >>> MALLOC.C 284
  1759. #define NOCCARGC  /* no argument count passing */
  1760. #include "stdio.h"
  1761. /*
  1762. ** Memory allocation of size bytes.
  1763. ** size  = Size of the block in bytes.
  1764. ** Returns the address of the allocated block,
  1765. ** else NULL for failure.
  1766. */
  1767. malloc(size) char *size; {
  1768.   return (_alloc(size, NO));
  1769.   }
  1770.  
  1771. >>> OTOI.C 368
  1772. #include "stdio.h"
  1773. /*
  1774. ** otoi -- convert unsigned octal string to integer nbr
  1775. **          returns field size, else ERR on error
  1776. */
  1777. otoi(octstr, nbr)  char *octstr;  int *nbr;  {
  1778.   int d,t; d=0;
  1779.   *nbr=0;
  1780.   while((*octstr>='0')&(*octstr<='7')) {
  1781.     t=*nbr;
  1782.     t=(t<<3) + (*octstr++ - '0');
  1783.     if ((t>=0)&(*nbr<0)) return ERR;
  1784.     d++; *nbr=t;
  1785.     }
  1786.   return d;
  1787.   }
  1788.  
  1789. >>> PAD.C 206
  1790. #define NOCCARGC  /* no argument count passing */
  1791. /*
  1792. ** Place n occurrences of ch at dest.
  1793. */
  1794. pad(dest, ch, n) char *dest, *n; int ch; {
  1795.   /* n is a fake unsigned integer */
  1796.   while(n--) *dest++ = ch;
  1797.   }
  1798.  
  1799. >>> POLL.C 442
  1800. #define NOCCARGC  /* no argument count passing */
  1801. #include "stdio.h"
  1802. #include "clib.def"
  1803. /*
  1804. ** Poll for console input or interruption
  1805. */
  1806. poll(pause) int pause; {
  1807.   int i;
  1808.   if(i = _hitkey())  i = _getkey();
  1809.   if(pause) {
  1810.     if(i == PAUSE) {
  1811.       i = _getkey();           /* wait for next character */
  1812.       if(i == ABORT) exit(7);  /* indicate abnormal exit */
  1813.       return (0);
  1814.       }
  1815.     if(i == ABORT) exit(7);
  1816.     }
  1817.   return (i);
  1818.   }
  1819.  
  1820. >>> PUTCHAR.C 172
  1821. #define NOCCARGC  /* no argument count passing */
  1822. #include "stdio.h"
  1823. /*
  1824. ** Write character to standard output. 
  1825. */
  1826. putchar(ch) int ch; {
  1827.   return (fputc(ch, stdout));
  1828.   }
  1829.  
  1830. >>> PUTS.C 194
  1831. #define NOCCARGC  /* no argument count passing */
  1832. #include "stdio.h"
  1833. /*
  1834. ** Write string to standard output. 
  1835. */
  1836. puts(string) char *string; {
  1837.   fputs(string, stdout);
  1838.   fputc('\n', stdout);
  1839.   }
  1840.  
  1841. >>> RENAME.C 763
  1842. #define NOCCARGC  /* no argument count passing */
  1843. #include "stdio.h"
  1844. #include "clib.def"
  1845. /*
  1846. ** Rename a file.
  1847. **  from = address of old filename.
  1848. **    to = address of new filename.
  1849. **  Returns NULL on success, else ERR.
  1850. */
  1851. rename(from, to) char *from, *to; {
  1852.   if(_rename(from, to)) return (NULL);
  1853.   return (ERR);
  1854.   }
  1855.  
  1856. _rename(old, new) char *old, *new; {
  1857. #asm
  1858.   push ds         ; ds:dx points to old name
  1859.   pop  es         ; es:di points to new name
  1860.   mov  di,[bp+4]  ; get "new" offset
  1861.   mov  dx,[bp+6]  ; get "old" offset
  1862.   mov  ah,56h     ; rename function
  1863.   int  21h        ; call bdos
  1864.   jnc  __ren1     ; error?
  1865.   xor  ax,ax      ; yes, return false
  1866.   jmp  __ren2 
  1867. __ren1:           ; no, set hi and lo
  1868.   mov  ax,1       ; return true
  1869. __ren2:
  1870. #endasm
  1871.   }
  1872.  
  1873. >>> REVERSE.C 220
  1874. #define NOCCARGC  /* no argument count passing */
  1875. /*
  1876. ** reverse string in place 
  1877. */
  1878. reverse(s) char *s; {
  1879.   char *j;
  1880.   int c;
  1881.   j = s + strlen(s) - 1;
  1882.   while(s < j) {
  1883.     c = *s;
  1884.     *s++ = *j;
  1885.     *j-- = c;
  1886.     }
  1887.   }
  1888.  
  1889. >>> REWIND.C 139
  1890. #define NOCCARGC  /* no argument count passing */
  1891. /*
  1892. ** Rewind file to beginning. 
  1893. */
  1894. rewind(fd) int fd; {
  1895.   return(cseek(fd, 0, 0));
  1896.   }
  1897.  
  1898. >>> SIGN.C 149
  1899. /*
  1900. ** sign -- return -1, 0, +1 depending on the sign of nbr
  1901. */
  1902. sign(nbr)  int nbr;  {
  1903.   if(nbr>0) return 1;
  1904.   if(nbr==0) return 0;
  1905.   return -1;
  1906.   }
  1907.  
  1908. >>> STRCAT.C 177
  1909. /*
  1910. ** concatenate t to end of s 
  1911. ** s must be large enough
  1912. */
  1913. strcat(s, t) char *s, *t; {
  1914.   char *d;
  1915.   d = s;
  1916.   --s;
  1917.   while (*++s) ;
  1918.   while (*s++ = *t++) ;
  1919.   return (d);
  1920.   }
  1921.  
  1922. >>> STRCHR.C 177
  1923. /*
  1924. ** return pointer to 1st occurrence of c in str, else 0
  1925. */
  1926. strchr(str, c) char *str, c; {
  1927.   while(*str) {
  1928.     if(*str == c) return (str);
  1929.     ++str;
  1930.     }
  1931.   return (0);
  1932.   }
  1933.  
  1934. >>> STRCMP.C 185
  1935. /*
  1936. ** return <0,   0,  >0 a_ording to
  1937. **       s<t, s=t, s>t
  1938. */
  1939. strcmp(s, t) char *s, *t; {
  1940.   while(*s == *t) {
  1941.     if(*s == 0) return (0);
  1942.     ++s; ++t;
  1943.     }
  1944.   return (*s - *t);
  1945.   }
  1946.  
  1947. >>> STRCPY.C 112
  1948. /*
  1949. ** copy t to s 
  1950. */
  1951. strcpy(s, t) char *s, *t; {
  1952.   char *d;
  1953.   d = s;
  1954.   while (*s++ = *t++) ;
  1955.   return(d);
  1956.   }
  1957.  
  1958. >>> STRLEN.C 114
  1959. /*
  1960. ** return length of s 
  1961. */
  1962. strlen(s) char *s; {
  1963.   char *t;
  1964.   t = s - 1;
  1965.   while (*++t) ;
  1966.   return (t - s);
  1967.   }
  1968.  
  1969. >>> STRNCAT.C 255
  1970. /*
  1971. ** concatenate n bytes max from t to end of s 
  1972. ** s must be large enough
  1973. */
  1974. strncat(s, t, n) char *s, *t; int n; {
  1975.   char *d;
  1976.   d = s;
  1977.   --s;
  1978.   while(*++s) ;
  1979.   while(n--) {
  1980.     if(*s++ = *t++) continue;
  1981.     return(d);
  1982.     }
  1983.   *s = 0;
  1984.   return(d);
  1985.   }
  1986.  
  1987. >>> STRNCMP.C 333
  1988. /*
  1989. ** strncmp(s,t,n) - Compares two strings for at most n
  1990. **                  characters and returns an integer
  1991. **                  >0, =0, or <0 as s is >t, =t, or <t.
  1992. */
  1993. strncmp(s, t, n) char *s, *t; int n; {
  1994.   while(n && *s==*t) {
  1995.     if (*s == 0) return (0);
  1996.     ++s; ++t; --n;
  1997.     }
  1998.   if(n) return (*s - *t);
  1999.   return (0);
  2000.   }
  2001.  
  2002. >>> STRNCPY.C 253
  2003. /*
  2004. ** copy n characters from sour to dest (null padding)
  2005. */
  2006. strncpy(dest, sour, n) char *dest, *sour; int n; {
  2007.   char *d;
  2008.   d = dest;
  2009.   while(n-- > 0) {
  2010.     if(*d++ = *sour++) continue;
  2011.     while(n-- > 0) *d++ = 0;
  2012.     }
  2013.   *d = 0;
  2014.   return (dest);
  2015.   }
  2016.  
  2017. >>> STRRCHR.C 315
  2018. /*
  2019. ** strrchr(s,c) - Search s for rightmost occurrance of c.
  2020. ** s      = Pointer to string to be searched.
  2021. ** c      = Character to search for.
  2022. ** Returns pointer to rightmost c or NULL.
  2023. */
  2024. strrchr(s, c) char *s, c; {
  2025.   char *ptr;
  2026.   ptr = 0;
  2027.   while(*s) {
  2028.     if(*s==c) ptr = s;
  2029.     ++s;
  2030.     }
  2031.   return (ptr);
  2032.   }
  2033.  
  2034. >>> TOASCII.C 77
  2035. /*
  2036. ** return ASCII equivalent of c
  2037. */
  2038. toascii(c) int c; {
  2039.   return (c);
  2040.   }
  2041.  
  2042. >>> TOLOWER.C 131
  2043. /*
  2044. ** return lower-case of c if upper-case, else c
  2045. */
  2046. tolower(c) int c; {
  2047.   if(c<='Z' && c>='A') return (c+32);
  2048.   return (c);
  2049.   }
  2050.  
  2051. >>> TOUPPER.C 137
  2052. /*
  2053. ** return upper-case of c if it is lower-case, else c
  2054. */
  2055. toupper(c) int c; {
  2056.   if(c<='z' && c>='a') return (c-32);
  2057.   return (c);
  2058.   }
  2059.  
  2060. >>> UNGETC.C 345
  2061. #define NOCCARGC  /* no argument count passing */
  2062. #include "stdio.h"
  2063. extern _nextc[];
  2064. /*
  2065. ** Put c back into file fd.
  2066. ** Entry:  c = character to put back
  2067. **        fd = file descriptor
  2068. ** Returns c if successful, else EOF.
  2069. */
  2070. ungetc(c, fd) int c, fd; {
  2071.   if(!_mode(fd) || _nextc[fd]!=EOF || c==EOF) return (EOF);
  2072.   return (_nextc[fd] = c);
  2073.   }
  2074.  
  2075. >>> UNLINK.C 520
  2076. #define NOCCARGC  /* no arg count passing */
  2077. #include "stdio.h"
  2078. #include "clib.def"
  2079. /*
  2080. ** Unlink (delete) the named file. 
  2081. ** Entry: fn = Null-terminated DOS file path\name.
  2082. ** Returns NULL on success, else ERR.
  2083. */
  2084. unlink(fn) char *fn; {
  2085.   fn;           /* load fn into ax */
  2086. #asm
  2087.   mov dx,ax     ; put fn in its place
  2088.   mov ah,41h    ; delete function code
  2089.   int 21h
  2090.   mov ax,0
  2091.   jnc __unlk    ; return NULL
  2092.   mov ax,-1     ; return ERR
  2093. __unlk:
  2094. #endasm
  2095.   }
  2096. #asm
  2097. _delete: jmp    _unlink
  2098.          public _delete
  2099. #endasm
  2100.  
  2101. >>> UTOI.C 365
  2102. #include "stdio.h"
  2103. /*
  2104. ** utoi -- convert unsigned decimal string to integer nbr
  2105. **          returns field size, else ERR on error
  2106. */
  2107. utoi(decstr, nbr)  char *decstr;  int *nbr;  {
  2108.   int d,t; d=0;
  2109.   *nbr=0;
  2110.   while((*decstr>='0')&(*decstr<='9')) {
  2111.     t=*nbr;t=(10*t) + (*decstr++ - '0');
  2112.     if ((t>=0)&(*nbr<0)) return ERR;
  2113.     d++; *nbr=t;
  2114.     }
  2115.   return d;
  2116.   }
  2117.  
  2118. >>> XTOI.C 729
  2119. #include stdio.h
  2120. /*
  2121. ** xtoi -- convert hex string to integer nbr
  2122. **         returns field size, else ERR on error
  2123. */
  2124. xtoi(hexstr, nbr) char *hexstr; int *nbr; {
  2125.   int d, b;  char *cp;
  2126.   d = *nbr = 0; cp = hexstr;
  2127.   while(*cp == '0') ++cp;
  2128.   while(1) {
  2129.     switch(*cp) {
  2130.       case '0': case '1': case '2':
  2131.       case '3': case '4': case '5':
  2132.       case '6': case '7': case '8':
  2133.       case '9':                     b=48; break;
  2134.       case 'A': case 'B': case 'C':
  2135.       case 'D': case 'E': case 'F': b=55; break;
  2136.       case 'a': case 'b': case 'c':
  2137.       case 'd': case 'e': case 'f': b=87; break;
  2138.        default: return (cp - hexstr);
  2139.       }
  2140.     if(d < 4) ++d; else return (ERR);
  2141.     *nbr = (*nbr << 4) + (*cp++ - b);
  2142.     }
  2143.   }
  2144.